package com.huawei.esdk.tp.professional.local.impl.service;

import org.apache.log4j.Logger;

import com.huawei.esdk.platform.professional.local.PlatformServiceFactoryEx;
import com.huawei.esdk.platform.professional.local.bean.SDKResponse;
import com.huawei.esdk.platform.professional.local.constant.PlatformNativeConstant;
import com.huawei.esdk.platform.professional.local.impl.utils.RSA2048Utils;
import com.huawei.esdk.platform.professional.local.service.common.PlatformKeyServiceEx;
import com.huawei.esdk.tp.professional.local.authentication.AuthorizeServiceEx;
import com.huawei.esdk.tp.professional.local.bean.Authenticate;
import com.huawei.esdk.tp.professional.local.bean.KeepAlive;
import com.huawei.esdk.tp.professional.local.bean.LoginRequest;
import com.huawei.esdk.tp.professional.local.bean.LoginRequestResponse;
import com.huawei.esdk.tp.professional.local.bean.Logout;
import com.huawei.esdk.tp.professional.local.bean.TPCommon;
import com.huawei.esdk.tp.professional.local.impl.utils.AES128Utils;
import com.huawei.esdk.tp.professional.local.impl.utils.Base64Utils;
import com.huawei.esdk.tp.professional.local.impl.utils.ClientProvider;
import com.huawei.esdk.tp.professional.local.impl.utils.Encrypt;
import com.huawei.esdk.tp.professional.local.impl.utils.ExceptionUtils;

public class AuthorizeServiceExImpl implements AuthorizeServiceEx
{
    /**
     * 日志对象
     */
    private static final Logger LOGGER = Logger.getLogger(AuthorizeServiceExImpl.class);
    
    private PlatformKeyServiceEx keyServiceEx = PlatformServiceFactoryEx.getService(PlatformKeyServiceEx.class);
    
    private TPCommon tPCommonClient = ((TPCommon)ClientProvider.getClient(TPCommon.class));
    
    private static AuthorizeServiceExImpl instance = null;
    
    public static synchronized AuthorizeServiceExImpl getInstance()
    {
        if (null == instance)
        {
            instance = new AuthorizeServiceExImpl();
        }
        return instance;
    }
    
    public Integer login(String userName, String password)
    {
        LOGGER.info("login method start");
        LoginRequest loginReq = new LoginRequest();
        loginReq.setClientType("API");
        loginReq.setUserName(userName);
        loginReq.setVersion(2);
        try
        {
            LoginRequestResponse loginResp = tPCommonClient.loginRequest(loginReq);
            if (loginResp.getResultCode() == 0)
            {
                Authenticate authenticate = new Authenticate();
                String encodePwd = Base64Utils.encode(loginResp.getRandomSequence());
                String pwd = Encrypt.getEncryptPassword(null == encodePwd ? "" : encodePwd, password);
                byte[] base64Pwd = Base64Utils.getFromBASE64(null == pwd ? "" : pwd);
                authenticate.setEncryptPassword(base64Pwd);
                Integer authCode = tPCommonClient.authenticate(authenticate).getResultCode();
                if (0 == authCode)
                {
                    LOGGER.info("begin to execute getPublicKey method");
                    SDKResponse<String> key = keyServiceEx.getPublicKey("RSA2048");
                    if (null == key || 0 != key.getResultCode())
                    {
                        LOGGER.info("failed to get publicKey");
                        return PlatformNativeConstant.FAILED_TO_GET_PUTLIC_KEY;
                    }
                    LOGGER.info("execute getPublicKey method completed");
                    
                    Integer setSecretKeyResultCode = setSecretKey();
                    if (null == setSecretKeyResultCode || 0 != setSecretKeyResultCode)
                    {
                        LOGGER.info("failed to get secretKey");
                        return PlatformNativeConstant.FAILED_TO_SET_SECRET_KEY;
                    }
                }
                LOGGER.info("login method end");
                return authCode;
            }
            LOGGER.info("login method end");
            return loginResp.getResultCode();
        }
        catch (Exception e)
        {
            LOGGER.error("login method error", e);
            return ExceptionUtils.processSoapException(e);
        }
    }
    
    public Integer logout()
    {
        LOGGER.info("logout method start");
        try
        {
            Integer errorCode = tPCommonClient.logout(new Logout()).getResultCode();
            LOGGER.info("logout method end");
            return errorCode;
        }
        catch (Exception e)
        {
            LOGGER.error("logout method error", e);
            return ExceptionUtils.processSoapException(e);
        }
    }
    
    public Integer keepAlive()
    {
        LOGGER.debug("keepAlive method start");
        try
        {
            Integer errorCode = tPCommonClient.keepAlive(new KeepAlive()).getResultCode();
            LOGGER.info("keepAlive method end");
            return errorCode;
        }
        catch (Exception e)
        {
            LOGGER.error("keepAlive method error", e);
            return ExceptionUtils.processSoapException(e);
        }
    }
    
    private Integer setSecretKey()
    {
        LOGGER.info("begin to execute setSecretKey method");
        byte[] secretKey = AES128Utils.getBT_KEY();
        byte[] iv = AES128Utils.getBT_IV();
        Integer resultCode = null;
        try
        {
            String secretKeyStr =
                Base64Utils.encode(RSA2048Utils.encode(AES128Utils.byte2Hex(secretKey).getBytes("UTF-8")));
            String ivStr = Base64Utils.encode(RSA2048Utils.encode(AES128Utils.byte2Hex(iv).getBytes("UTF-8")));
            
            resultCode = keyServiceEx.setSecretKey("AES128", secretKeyStr, ivStr);
        }
        catch (Exception e)
        {
            LOGGER.error("failed to setSecretKey");
            resultCode = PlatformNativeConstant.FAILED_TO_SET_SECRET_KEY;
        }
        LOGGER.info("execute setSecretKey method completed");
        return resultCode;
    }
}
